package com.mobileClientKernel.android.commonLayer;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.Date;

public class JJLog {
    //    public static boolean DEBUG = true;
    public static final String LOG_TAG = "JJLog";
    private static final String DEBUG_TAG = "JJLog";
    private static boolean isSave;
    private static File currentLogFile;
    private static StringBuffer stringBuffer;
    private static Context context;
    private static File logDir;
    private static String deviceId;
    private static String md5Code;
    private static String secretKey;
    private static boolean DEBUG;
    private static boolean productionMode;
    // 全局数组
    private final static String[] strDigits = {"0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
    private static final int CREATE_MSG = 0;
    private static final int WRITE_MSG = 1;
    private static final int FLUSH_MSG = 2;
    private static Handler mLogHandler;
    private static Looper myLooper;
    private static LogThread mLogThread;
    public static void init(Context context, boolean isSave, boolean productionMode) {
        JJLog.context=context;
        JJLog.isSave = isSave;
        JJLog.productionMode=productionMode;

        logDir = CacheManager.getCacheFile(context, "logs");
        if (!logDir.exists()) {
            logDir.mkdirs();
        }

        Log.i(DEBUG_TAG,"[init] isSave = "+isSave+"  DEBUG = "+DEBUG);
        if(isSave){
            mLogThread = new LogThread();
            mLogThread.start();
        }
    }

    private static void createFile(){
        //创建本次启动log文件
        if (currentLogFile==null||!currentLogFile.exists()||!currentLogFile.isFile()){
            SimpleDateFormat format1 = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA);
            String currntTime = format1.format(new Date(System.currentTimeMillis()));
            currentLogFile = new File(logDir, currntTime + ".txt");
            try {
                currentLogFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }

            stringBuffer = new StringBuffer();
            stringBuffer.append("**************************************************************");
            stringBuffer.append("\r\n");
            stringBuffer.append("** Started Logging");
            stringBuffer.append("\r\n");
            stringBuffer.append("Application Identifier:"+ UniqueIDUtil.getDeviceId(context));
            stringBuffer.append("\r\n");
            stringBuffer.append("Application Version:"+ UniqueIDUtil.getVersionName(context));
            stringBuffer.append("\r\n");
            stringBuffer.append("Date  Time:   " + JJLog.getDateStr());
            stringBuffer.append("\r\n");
            stringBuffer.append("**************************************************************");
            stringBuffer.append("\r\n");

            deviceId = UniqueIDUtil.getDeviceId(context);
            md5Code = getMD5Code( deviceId);

            secretKey = secretKey(md5Code, 10).substring(0,8);
            cleanOldLog(logDir);
        }
    }

    private JJLog() {
    }

    public static void debug(boolean key){//RN默认日志开关是关闭的，第一次调用key为ture
        Log.i(DEBUG_TAG,"[debug] key = "+key);
        //deleteAllFiles();

        if(key){
            if(!isSave){//写日志功能默认是开启的，所以如果写日志已经开启则不需要重新开启
                mLogThread = new LogThread();
                mLogThread.start();
            }
        }else{
            Log.i(DEBUG_TAG,"[debug] myLooper = "+myLooper);
            if(myLooper!=null) {
                Log.i(DEBUG_TAG,"[debug] myLooper.quit()");
                myLooper.quit();
            }
        }
        isSave = key;
        DEBUG = key;
    }

    public static final void d(String log) {
        if (DEBUG){
            Log.d(LOG_TAG,log);
        }
        if(DEBUG && isSave){
            sendMessageToThread(JJLog.getDateStr() +" [d] "+"["+LOG_TAG+"] "+log);

        }
        //save2File(CommonUtils.getDateStr()+" [d] "+log);

    }



    public static final void _d(String TAG, String log) {
        if (DEBUG) {
            Log.d(TAG,""+log);
        }

        if(DEBUG && isSave){
            sendMessageToThread(JJLog.getDateStr() +" [d] "+"["+TAG+"] "+log);
        }
        //save2File(CommonUtils.getDateStr()+" [d] "+log);
    }

    public static final void _i(String TAG, String log) {
        if (DEBUG){
            Log.i(TAG,""+log);
        }
        if(isSave){
            sendMessageToThread(DEBUG?JJLog.getDateStr() +" [i] "+"["+TAG+"] "+log:" [i] "+"["+TAG+"] "+log);
        }
    }


    public static final void _w(String TAG, String log) {
        if (DEBUG){
            Log.w(TAG,""+log);
        }
        if(isSave){
            sendMessageToThread(DEBUG?JJLog.getDateStr() +" [w] "+"["+TAG+"] "+log:" [w] "+"["+TAG+"] "+log);
        }

    }

    public static final void _e(String TAG, String log) {
        if (DEBUG){
            Log.e(TAG, "" + log);
        }
        if(isSave){
            sendMessageToThread(DEBUG?JJLog.getDateStr() +" [e] "+"["+TAG+"] "+log:" [e] "+"["+TAG+"] "+log);
        }

    }

    public static final void e(String log) {
        if (DEBUG){
            Log.e(LOG_TAG, "" + log);
        }
        if(isSave){
            sendMessageToThread(DEBUG?JJLog.getDateStr() +" [e] "+"["+LOG_TAG+"] "+log:" [e] "+"["+LOG_TAG+"] "+log);
        }
    }

    public static final void i(String log) {
        if (DEBUG){
            Log.i(LOG_TAG, "" + log);
        }
        if(isSave){
            sendMessageToThread(DEBUG?JJLog.getDateStr() +" [i] "+"["+LOG_TAG+"] "+log:" [i] "+"["+LOG_TAG+"] "+log);
        }
    }

    public static final void v(String log) {
        if (DEBUG){
            Log.v(LOG_TAG, "" + log);
        }
        if(isSave){
            sendMessageToThread(DEBUG?JJLog.getDateStr() +" [v] "+"["+LOG_TAG+"] "+log:" [v] "+"["+LOG_TAG+"] "+log);
        }
    }

    public static final void w(String log) {
        if (DEBUG){
            Log.w(LOG_TAG, "" + log);
        }
        if(isSave){
            sendMessageToThread(DEBUG?JJLog.getDateStr() +" [w] "+"["+LOG_TAG+"] "+log:" [w] "+"["+LOG_TAG+"] "+log);
        }
    }

    private static void sendMessageToThread(String msg){
        if(isSave && mLogHandler!=null){
            mLogHandler.obtainMessage(WRITE_MSG, msg).sendToTarget();
        }
    }

    public static void save2File(String log) {
        if (!isSave)
            return;
        if(!DEBUG){
            log = JJLog.getDateStr() + log;
        }

        stringBuffer.append(log+"\r\n");
        if (stringBuffer.length()>1000) {

            if (currentLogFile == null) {
                Log.e(DEBUG_TAG, "currentLogFile is null");
                return;
            }

            if (currentLogFile.length() > 5 * 1024 * 1024) {
                //创建本次启动log文件
                SimpleDateFormat format1 = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA);
                String currntTime = format1.format(new Date(System.currentTimeMillis()));
                currentLogFile = new File(logDir, currntTime + ".txt");
                try {
                    currentLogFile.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e(DEBUG_TAG, "create log file IOException");
                }


                stringBuffer.insert(0, "**************************************************************");
                stringBuffer.append("\r\n");
                stringBuffer.insert(0, "Restarting Logging: THIS IS A CONTINUATION OF PREVIOUS LOGGING");
                stringBuffer.append("\r\n");
                stringBuffer.insert(0, "Application Identifier:" + UniqueIDUtil.getDeviceId(context));
                stringBuffer.append("\r\n");
                stringBuffer.insert(0, "Application Version:" + UniqueIDUtil.getVersionName(context));
                stringBuffer.append("\r\n");
                stringBuffer.insert(0, "Date  Time:   " + JJLog.getDateStr());
                stringBuffer.append("\r\n");
                stringBuffer.insert(0, "**************************************************************");
                stringBuffer.append("\r\n");
                writeText2File(currentLogFile.getAbsolutePath(), desLog(stringBuffer.toString(), secretKey));


            } else {
                writeText2File(currentLogFile.getAbsolutePath(), desLog(stringBuffer.toString(), secretKey));

            }

            stringBuffer.setLength(0);

        }


    }

    /**
     * 删除旧的日志文件
     *
     * @param logDir
     */
    private static synchronized void cleanOldLog(File logDir) {


        if (logDir == null) return;
        File[] files = logDir.listFiles();

        if (files == null || files.length == 0) {
            return;
        }
        if (files.length <= 3) return;

        Arrays.sort(files);
        for (int i = 0; i < files.length-3; i++) {
            files[i].delete();
        }
    }

    /**
     * 刷文件
     */
    public static void flushLogs(){
        if (isSave&&mLogHandler!=null){
            mLogHandler.obtainMessage(FLUSH_MSG, "").sendToTarget();
        }

    }

    /**
     * 删除log文件
     */
    public static void deleteAllFiles(){
        if (logDir == null) return;
        File[] files = logDir.listFiles();
        if (files == null || files.length == 0) return;
        for (int i = 0; i < files.length; i++) {
            files[i].delete();
        }
    }



    /**
     * 追加写入文件：使用FileWriter,写入后自动换行
     *
     * @param fileName
     * @param content
     */
    public static void writeText2File(String fileName, String content) {
        //Log.i(DEBUG_TAG,"[writeText2File] content = "+content);
        try {
            //追加形式写文件
            FileWriter writer = new FileWriter(fileName, true);

            writer.write(content);
            writer.write("***\r\n");
            writer.flush();
            writer.close();




        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static String getMD5Code(String strObj) {
        String resultString = null;
        try {
            resultString = new String(strObj);
            MessageDigest md = MessageDigest.getInstance("MD5");
            // md.digest() 该函数返回值为存放哈希值结果的byte数组
            resultString = byteToString(md.digest(strObj.getBytes()));
        } catch (NoSuchAlgorithmException ex) {
            ex.printStackTrace();
        }
        return resultString;
    }
    // 转换字节数组为16进制字串
    private static String byteToString(byte[] bByte) {
        StringBuffer sBuffer = new StringBuffer();
        for (int i = 0; i < bByte.length; i++) {
            sBuffer.append(byteToArrayString(bByte[i]));
        }
        return sBuffer.toString();
    }
    // 返回形式为数字跟字符串
    private static String byteToArrayString(byte bByte) {
        int iRet = bByte;

        if (iRet < 0) {
            iRet += 256;
        }
        int iD1 = iRet / 16;
        int iD2 = iRet % 16;
        return strDigits[iD1] + strDigits[iD2];
    }


    public static String desLog(String log,String secretKey){
        String des = log;
        // todo 加密
//        try {
//            des = DESUtil.encryptDES(log.toString(), secretKey);
//
//        } catch (Exception e) {
//            e.printStackTrace();
//        }

        return des;
    }


    public static String secretKey(String sourse,int num){
        String des = sourse;

        while (num>0){
            des= getMD5Code(des);
            Log.d("CommonUtils","des = "+des );
            num--;
            Log.d("CommonUtils","num = "+num );
        }


        Log.d("CommonUtils","des final = "+des );
        return des;
    }



    static class LogThread extends Thread {
        @Override
        public void run() {
            createFile();

            Looper.prepare();//1、初始化Looper
            //建立消息循环的步骤
            myLooper = Looper.myLooper();
            Log.i(DEBUG_TAG,"[LogThread] myLooper = "+myLooper);

            Log.i(DEBUG_TAG, "LogThread myLooper.prepare()");
            mLogHandler = new Handler(){//2、绑定handler到CustomThread实例的Looper对象
                public void handleMessage (Message msg) {//3、定义处理消息的方法
                    switch(msg.what) {
                        case WRITE_MSG:
                            //Log.i(DEBUG_TAG, "LogThread receive msg:" + (String) msg.obj);
                            save2File((String)msg.obj);
                            break;
                        case FLUSH_MSG:
                            //Log.i(DEBUG_TAG, "LogThread FLUSH_MSG");
                            writeText2File(currentLogFile.getAbsolutePath(), desLog(stringBuffer.toString(), secretKey));
                            break;
                    }
                }
            };
            Log.i(DEBUG_TAG, "LogThread Looper.loop()");
            Looper.loop();//4、启动消息循环
            Log.i(DEBUG_TAG, "子线程退出");
        }
    }

    private static SimpleDateFormat LOGFORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
    public static String getDateStr() {
        return LOGFORMAT.format(new Date(System.currentTimeMillis()));
    }
}
